每個React網頁 都是由基礎價夠堆疊出來,對於使用者,只能看到結果
所以按照元件一層層嵌套下去,當然沒問題。但是如果最底層的按鈕要返回 他已經登出這件事情怎麼辦呢?
npm 安裝
npm i react-router-dom
一樣是從app.js開始,但不一樣的事要從app.js的外面著手
app.js移動 至 新資料夾:page =>重新命名為app.jsx
引用自創的全域框架 ContextProvider.jsx
從專案 > src > index.js 開始
/*file index.js*/
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.scss';//global css
import App  from './page/App';/*app.js移動 至 新資料夾:page =>重新命名為app.jsx*/
import { ContextProvider } from './constant/ContextProvider';
import { BrowserRouter, Route, Routes } from "react-router-dom";
/*Route寫法可能因為版本 引用元件會完全不一樣 但是架構類似*/
ReactDOM.render(
    <React.StrictMode>
        <ContextProvider>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<App />} />
                </Routes>
            </BrowserRouter>
        </ContextProvider>
    </React.StrictMode>,
    document.getElementById('root')
);
src > 新增資料夾:constant > 新增檔案:ContextProvider.jsx
/*file ContextProvider.jsx*/
import { createContext, useContext, useState } from "react";
import { redirect } from "react-router-dom";/*這裡轉址 也因為版本import元件不一樣寫法差不多*/
const StateContext = createContext({
    user: null,
    token: null,
    notification: null,
    setUser: () => { },
    setToken: () => { },
    setNotification: () => { },
    setLoading: () => { }
});
export const ContextProvider = ({ children }) => {
    const [user, _setUser] = useState(localStorage.getItem('user') ? JSON.parse(localStorage.getItem('user')) : {});
    const [token, _setToken] = useState(localStorage.getItem('ACCESS_TOKEN'));
    const [notification, _setNotification] = useState('');
    const [isLoading, _setLoading] = useState(true);
    const setUser = (user) => {
        if (user && typeof user === 'object' && user['id']) {
            _setUser(user);
            localStorage.setItem('user', JSON.stringify(user));
        } else if (user === 'logout') {
            _setUser(null);
            localStorage.removeItem('user');
            setToken(null);
            return redirect('/')
        } else {
            _setUser(null);
            localStorage.removeItem('user');
            setToken(null);
            return redirect('/login', {
                onFinish: () => setNotification('登入逾期失效')
            })
        }
    }
    const setToken = (token) => {
        if (token) {
            _setToken(token);
            localStorage.setItem('ACCESS_TOKEN', token);
        } else {
            _setToken(null);
            localStorage.removeItem('ACCESS_TOKEN');
        }
    }
    const setNotification = (message) => {
        _setNotification(message);
        setTimeout(() => {
            _setNotification('');
        }, 5000)
    }
    const setLoading = (isLoading) => {
        if (isLoading) {
            _setLoading(true);
        } else {
            _setLoading(false);
        }
    }
    return (
        <StateContext.Provider value={{
            user,
            setUser,
            token,
            setToken,
            notification,
            setNotification,
            setLoading
        }}>
            {isLoading &&
                <div id="loading" className="d-flex justify-content-center align-items-center">
                    <div className="spinner-border text-primary" role="status">
                        <span className="visually-hidden">Loading...</span>
                    </div>
                </div>
            }
            {notification && <div className="alert alert-box alert-success">{notification}</div>}
            {children}
        </StateContext.Provider>
    )
}
export const userStateContext = () => useContext(StateContext)
補充css外觀
$theme-colors: ( 'primary':#407855 );
@import '~bootstrap/scss/bootstrap';
#loading {
    position: absolute;
    top: 0;
    left: 0;
    min-width: 100vw;
    min-height: 100vh;
    background-color: rgba(111,111,111,0.35);
    z-index: 2090;
    cursor: progress;
}
到這裡基本上可以看到 綠色(#4407855)的按鈕跟loading了
/*file app.jsx*/
import React, { useEffect } from 'react';
import { userStateContext } from "../constant/ContextProvider";
import 'sweetalert2/src/sweetalert2.scss'
import { useNavigate } from "react-router-dom";
function App() {
    const { user, setUser, token, setToken, setLoading, setNotification } = userStateContext();/*引用全域函數*/
    const navigate = useNavigate();
    useEffect(() => {/*初始化*/
        setLoading(false);
    }, []);/*這個矩陣是很重要的*/
    function fakeLogin() {
        setLoading(true);
        setToken('kasnvlawejnflasdfjklfsadnf');
        setUser({ id: '新用戶', email: "dsafsa@afs.com" });
        setNotification('登入成功');
        navigate("about", {
            onFinish: () => setLoading(false)
        });
    }
    return (
        <div className="App">
            {user && Object.keys(user).length && user['id'] ? "歡迎" + user['id'] : null}
            <button className="btn btn-primary" onClick={fakeLogin} >登入</button>
        </div>
    );
}
export default App;
/*file: index.js*/
import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.scss';//gloable css
import App from './page/App';
import About from './page/About';/* 引入新頁面*/
import { ContextProvider } from './constant/ContextProvider';
import { BrowserRouter, Route, Routes } from "react-router-dom";
ReactDOM.render(
    <React.StrictMode>
        <ContextProvider>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<App />} />
                    <Route path='about' element={<About />} />/* 給予路由 yourDomain/about*/
                </Routes>
            </BrowserRouter>
        </ContextProvider>
    </React.StrictMode>,
    document.getElementById('root')
);
新增檔案 src > page > About.jsx
/*file: About.jsx*/
import React, { useEffect } from 'react';
import { userStateContext } from "../constant/ContextProvider";
function About() {
    const { user } = userStateContext();/*引用全域函數*/
    return (
        <div className="App">
            {user && Object.keys(user).length && user['id'] ? "歡迎" + user['id'] : null} 登入
        </div>
    );
}
export default About;

到這邊基本上就可以達成
react其實有點小小缺點,資料只能下向傳承,所以要跨區塊傳遞,會有點小麻煩。
我寫了javascript兩年,沒人教的情況下,有些好用的方法真的會不知道,知道都是抄來的
以前沒有人可以問,現在有ChatGPT可以問。我的文章不斷要求不使用ChatGPT。
用在ChatGPT一出來,就開始用。用了非常多,而且都是連續問很多問題。(沒辦法上傳gif檔)
我在這裡可以很肯定地說,如果你是要最上面金字塔圖 相鄰兩區塊的問題 已經是複雜度的極限。
ChatGPT對於橫向問題處理很好,但對於1.多系統 2.縱深架構,他會提出的答案,效果可能不夠好。
技術參考來源: 全域資料傳遞:https://www.youtube.com/watch?v=qJq9ZMB2Was&ab_channel=TheCodeholic